package com.opennews.openplatform.familyexpenseapi.controller

import com.opennews.openplatform.familyexpenseapi.dto.income.expense.detail.CreateIncomeExpenseDetailDto
import com.opennews.openplatform.familyexpenseapi.dto.income.expense.detail.IncomeExpenseDetailQueryArgument
import com.opennews.openplatform.familyexpenseapi.dto.income.expense.detail.UpdateIncomeExpenseDetailDto
import com.opennews.openplatform.familyexpenseapi.service.IncomeExpenseDetailService
import com.opennews.openplatform.myspringbootcore.dto.ApiResponse
import com.opennews.openplatform.myspringbootcore.dto.IdentityDto
import com.opennews.openplatform.myspringbootcore.util.DateHelper.parseFromLongDateTime
import com.opennews.openplatform.myspringbootcore.util.getSuccessResponse
import com.opennews.openplatform.myspringbootmvccore.security.RequestIdentityExtractor
import jakarta.validation.Valid
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import java.math.BigDecimal

@RestController
@RequestMapping("/income-expense-detail")
class IncomeExpenseDetailController(
    private val incomeExpenseDetailService: IncomeExpenseDetailService,
    private val requestIdentityExtractor: RequestIdentityExtractor,
) {
    @GetMapping("/query-list-with-summary-by-account-group")
    fun queryListWithSummaryByAccountGroup(
        @RequestParam pageSize: Int,
        @RequestParam pageIndex: Int,
    ): ResponseEntity<ApiResponse<List<Map<String, Any?>>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()
        val result = incomeExpenseDetailService.queryListWithSummaryByAccountGroup(accountGroupId, pageSize, pageIndex)

        return getSuccessResponse(result)
    }

    @GetMapping("/query-list-by-account-group")
    fun queryListByAccountGroup(
        @RequestParam startDate: String,
        @RequestParam endDate: String,
        @RequestParam keyword: String,
        @RequestParam keywordsSearchCondition: String,
        @RequestParam type: String,
        @RequestParam detailType: String,
        @RequestParam paymentType: String,
        @RequestParam bankCardId: String,
        @RequestParam pageSize: Int,
        @RequestParam pageIndex: Int,
    ): ResponseEntity<ApiResponse<List<Map<String, Any?>>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()

        val queryArgument = IncomeExpenseDetailQueryArgument().apply {
            this.startDate =
                if (startDate.isBlank()) null else parseFromLongDateTime(startDate)

            this.endDate = if (endDate.isBlank()) null else parseFromLongDateTime(endDate)
            this.keyword = keyword
            this.keywordsSearchCondition = keywordsSearchCondition
            this.type = type
            this.detailType = detailType
            this.paymentType = paymentType
            this.bankCardId = bankCardId
            this.accountGroupId = accountGroupId
            this.pageSize = pageSize
            this.pageIndex = pageIndex
        }

        val result = incomeExpenseDetailService.queryListByAccountGroup(queryArgument)
        return getSuccessResponse(result)
    }

    @GetMapping("/query-total-amount-by-account-group")
    fun queryTotalAmountByAccountGroup(
        @RequestParam startDate: String,
        @RequestParam endDate: String,
        @RequestParam keyword: String,
        @RequestParam keywordsSearchCondition: String,
        @RequestParam type: String,
        @RequestParam detailType: String,
        @RequestParam paymentType: String,
        @RequestParam bankCardId: String,
    ): ResponseEntity<ApiResponse<BigDecimal>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()

        val queryArgument = IncomeExpenseDetailQueryArgument().apply {
            this.startDate =
                if (startDate.isBlank()) null else parseFromLongDateTime(startDate)

            this.endDate = if (endDate.isBlank()) null else parseFromLongDateTime(endDate)
            this.keyword = keyword
            this.keywordsSearchCondition = keywordsSearchCondition
            this.type = type
            this.detailType = detailType
            this.paymentType = paymentType
            this.bankCardId = bankCardId
            this.accountGroupId = accountGroupId
        }

        val result = incomeExpenseDetailService.queryTotalAmountByAccountGroup(queryArgument)
        return getSuccessResponse(result)
    }

    @GetMapping("/query-details")
    fun queryDetails(@RequestParam id: String): ResponseEntity<ApiResponse<Map<String, Any?>>> {
        val result =
            incomeExpenseDetailService.queryDetails(requestIdentityExtractor.getClaims().accountGroupId.asString(), id)
        return getSuccessResponse(result)
    }

    @GetMapping("/query-credit-card-bill")
    fun queryCreditCardBill(
        @RequestParam bankCardId: String,
        @RequestParam statementDate: String,
        @RequestParam pageSize: Int,
        @RequestParam pageIndex: Int,
    ): ResponseEntity<ApiResponse<List<Map<String, Any?>>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()

        val result = incomeExpenseDetailService.queryCreditCardBill(
            accountGroupId,
            pageSize,
            pageIndex,
            bankCardId,
            parseFromLongDateTime(statementDate),
        )

        return getSuccessResponse(result)
    }

    @GetMapping("/query-credit-card-bill-amount")
    fun queryCreditCardBillAmount(
        @RequestParam bankCardId: String,
        @RequestParam statementDate: String,
    ): ResponseEntity<ApiResponse<BigDecimal>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()

        val result = incomeExpenseDetailService.queryCreditCardBillAmount(
            accountGroupId,
            bankCardId,
            parseFromLongDateTime(statementDate),
        )

        return getSuccessResponse(result)
    }

    @GetMapping("/query-coordinates")
    fun queryCoordinates(@RequestParam year: String): ResponseEntity<ApiResponse<List<Map<String, Any>>>> {
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()
        val result = incomeExpenseDetailService.queryCoordinates(accountGroupId, year)

        return getSuccessResponse(result)
    }

    @PostMapping("/add")
    fun add(@Valid @RequestBody data: CreateIncomeExpenseDetailDto): ResponseEntity<ApiResponse<Any?>> {
        val claims = requestIdentityExtractor.getClaims()
        incomeExpenseDetailService.add(claims.accountGroupId.asString(), claims.username, data)

        return getSuccessResponse()
    }

    @PostMapping("/update")
    fun update(@Valid @RequestBody data: UpdateIncomeExpenseDetailDto): ResponseEntity<ApiResponse<Any?>> {
        val claims = requestIdentityExtractor.getClaims()
        incomeExpenseDetailService.update(claims.accountGroupId.asString(), claims.username, data)

        return getSuccessResponse()
    }

    @PostMapping("/delete")
    fun delete(@Valid @RequestBody data: IdentityDto): ResponseEntity<ApiResponse<Any?>> {
        val id = data.id.asString()
        val accountGroupId = requestIdentityExtractor.getClaims().accountGroupId.asString()
        incomeExpenseDetailService.delete(accountGroupId, listOf(id))

        return getSuccessResponse()
    }
}